package com.xzq.socket.nio;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.Set;

/**
 * @Author xzq
 * @Description //TODO
 * @Date 2021/11/18 19:43
 * @Version 1.0.0
 **/
public abstract class ChannelAdapter extends Thread{

    private Selector selector;
    private ChannelHandler channelHandler;
    private Charset charset;

    public ChannelAdapter( Selector selector, Charset charset) {
        this.selector = selector;
        this.charset = charset;
    }

    @Override
    public void run() {
        while (true) {
            try {
                selector.select();
                Set<SelectionKey> selectedKeys = selector.selectedKeys();
                Iterator<SelectionKey> iter = selectedKeys.iterator();
                SelectionKey key = null;
                while (iter.hasNext()) {
                    key = iter.next();
                    iter.remove();
                    handlerInput(key);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    private void handlerInput(SelectionKey key) throws IOException {
        if (!key.isValid()) {
            return;
        }
        //客户端SocketChannel
        Class<?> superclass = key.channel().getClass().getSuperclass();
        if (superclass == SocketChannel.class) {
            SocketChannel sc =(SocketChannel) key.channel();
            if (key.isConnectable()) {
                if (sc.finishConnect()) {
                    channelHandler = new ChannelHandler(sc, charset);
                    channelActive(channelHandler);
                    sc.register(selector, SelectionKey.OP_READ);
                }else{
                    System.exit(1);
                }
            }
        }

        //服务端ServerSocketChannel
        if (superclass == ServerSocketChannel.class) {
            if (key.isAcceptable()) {
                ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
                SocketChannel sc = ssc.accept();
                sc.configureBlocking(false);
                sc.register(selector, SelectionKey.OP_READ);
                channelHandler= new ChannelHandler(sc, charset);
                channelActive(channelHandler);
            }
        }

        if (key.isReadable()) {
            SocketChannel sc =(SocketChannel) key.channel();
            ByteBuffer readBuffer = ByteBuffer.allocate(1024);
            int readBytes = sc.read(readBuffer);
            if (readBytes > 0) {
                readBuffer.flip();
                byte[] bytes = new byte[readBuffer.remaining()];
                readBuffer.get(bytes);
                channelRead(channelHandler, new String(bytes, charset));
            } else if (readBytes < 0) {
                key.cancel();
                sc.close();
            }
        }

    }


    //读取消息抽象类
    protected abstract void channelRead(ChannelHandler channelHandler, String s);

    //连接通知抽象类
    protected abstract void channelActive(ChannelHandler channelHandler);

}
